/*
 * Copyright (c) 2001-2007, Inversoft, All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 */
package org.inversoft.vertigo.persistence;

import java.util.List;

import com.google.inject.ImplementedBy;

import org.inversoft.vertigo.domain.Identifiable;
import org.inversoft.vertigo.domain.SoftDelete;
import org.inversoft.vertigo.jpa.JPAPersistenceService;

/**
 * <p>
 * This interface defines the core CRUD operations for any object.
 * </p>
 *
 * @author  Brian Pontarelli
 */
@ImplementedBy(JPAPersistenceService.class)
public interface PersistenceService {
    /**
     * This locates all instances of an Object by class. This could be extremely heavy weight
     * if the number of Objects of the type are large. Therefore, only use this method when you
     * know that the total number of Object instances in the DB is low.
     *
     * @param   type The type of Objects to fetch.
     * @return  A List of the Objects found in the database.
     */
    <T> List<T> findAllByType(Class<T> type);

    /**
     * This locates all instances of an Object by class. This could be extremely heavy weight
     * if the number of Objects of the type are large. Therefore, only use this method when you
     * know that the total number of Object instances in the DB is low.
     *
     * @param   type The type of Objects to fetch.
     * @param   includeInactive Determines if this should return all the instances of the Object
     *          including those instances that are marked as inactive and are {@link SoftDelete}
     *          objects.
     * @return  A List of the Objects found in the database.
     */
    <T extends SoftDelete> List<T> findAllByType(Class<T> type, boolean includeInactive);

    /**
     * This locates a subset of all the instances of an Object by class. This helps when paginating
     * over all of the instances of a specific type.
     *
     * @param   type The type of Objects to fetch.
     * @param   start The location in the total set of possible Objects to start from. This is zero
     *          based.
     * @param   number The number of results to return in this page.
     * @return  A List of the Objects found in the database.
     */
    <T> List<T> findByType(Class<T> type, int start, int number);

    /**
     * This locates a subset of all the instances of an Object by class. This helps when paginating
     * over all of the instances of a specific type.
     *
     * @param   type The type of Objects to fetch.
     * @param   start The location in the total set of possible Objects to start from. This is zero
     *          based.
     * @param   number The number of results to return in this page.
     * @param   includeInactive Determines if this should return all the instances of the Object
     *          including those instances that are marked as inactive and are {@link SoftDelete}
     *          objects.
     * @return  A List of the Objects found in the database.
     */
    <T extends SoftDelete> List<T> findByType(Class<T> type, int start, int number, boolean includeInactive);

    /**
     * Executes the given query and returns all of the results from the query.
     *
     * @param   type The type of Objects to fetch.
     * @param   query The EJB3 query language query string.
     * @param   params A list of parameters that are parameterized within the query string (e.g.
     *          select user from User user where firstName = ?)
     * @return  A List of the Objects found in the database.
     */
    <T> List<T> queryAll(Class<T> type, String query, Object... params);

    /**
     * Executes the given query and returns a subset of the results from the query. This method is
     * useful for paginating over a search results from a query.
     *
     * @param   type The type of Objects to fetch.
     * @param   query The EJB3 query language query string.
     * @param   start The location in the total set of possible Objects to start from. This is zero
     *          based.
     * @param   number The number of results to return in this page.
     * @param   params A list of parameters that are parameterized within the query string (e.g.
     *          select user from User user where firstName = ?)
     * @return  A List of the Objects found in the database.
     */
    <T> List<T> query(Class<T> type, String query, int start, int number, Object... params);

    /**
     * Executes the given query and returns the first result from the query.
     *
     * @param   type The type of Objects to fetch.
     * @param   query The EJB3 query language query string.
     * @param   params A list of parameters that are parameterized within the query string (e.g.
     *          select user from User user where firstName = ?)
     * @return  The first result if there are 1 or more results, otherwise null.
     */
    <T> T queryFirst(Class<T> type, String query, Object... params);

    /**
     * Executes the given named query and returns all the results from the query.
     *
     * @param   type The type of Objects to fetch.
     * @param   query The named query.
     * @param   params A list of parameters that are parameterized within the query string (e.g.
     *          select user from User user where firstName = ?)
     * @return  A List of the Objects found in the database.
     */
    <T> List<T> namedQueryAll(Class<T> type, String query, Object... params);

    /**
     * Executes the given named query and returns a subset of the results from the query. This method is
     * useful for paginating over a search results from a query.
     *
     * @param   type The type of Objects to fetch.
     * @param   query The named query.
     * @param   start The location in the total set of possible Objects to start from. This is zero
     *          based.
     * @param   number The number of results to return in this page.
     * @param   params A list of parameters that are parameterized within the query string (e.g.
     *          select user from User user where firstName = ?)
     * @return  A List of the Objects found in the database.
     */
    <T> List<T> namedQuery(Class<T> type, String query, int start, int number, Object... params);

    /**
     * Executes the given named query and returns the first result from the query.
     *
     * @param   type The type of Objects to fetch.
     * @param   query The named query.
     * @param   params A list of parameters that are parameterized within the query string (e.g.
     *          select user from User user where firstName = ?)
     * @return  The first result if there are 1 or more results, otherwise null.
     */
    <T> T namedQueryFirst(Class<T> type, String query, Object... params);

    /**
     * Locates the entity with the given type and primary key (id).
     *
     * @param   type The type of Object to fetch.
     * @param   id The primary key of the Object to fetch.
     * @return  The Object or null if it doesn't exist.
     */
    <T extends Identifiable> T findById(Class<T> type, int id);

    /**
     * Saves or updates the entity bean to the database.
     *
     * @param   entityBean The entity bean to persist.
     * @return  True if the object was persisted. False if the object was not persisted because of a
     *          unique key constraint.
     * @throws  javax.persistence.PersistenceException If there were any database issues while persisting
     *          the Object. This does not include unique key exceptions (i.e. EntityExistsException).
     */
    boolean persist(Object entityBean);

    /**
     * Removes the bean with the given type and primary key. Since this uses a primary key to remove
     * the instance, this method will only work with identified instances. In addition, if the object
     * type passed in is {@link SoftDelete} than this method will update the active flag and perform
     * an update rather than a delete.
     *
     * @param   type The type of Object to remove.
     * @param   id The primary key of the Object to remove.
     * @return  True if the entity was removed, false if it wasn't because it doesn't exist.
     */
    <T extends Identifiable> boolean delete(Class<T> type, int id);

    /**
     * Removes the given entity bean. If the object type passed in is {@link SoftDelete} than this
     * method will update the active flag and perform an update rather than a delete.
     *
     * @param   bean The Object to remove.
     */
    void delete(Object bean);
}